//
//  CBCentralManager+QNConnectOverTime.m
//  QNCentralModule
//
//  Created by donyau on 2019/4/1.
//  Copyright © 2019 CocoaPods. All rights reserved.
//

#import "CBCentralManager+QNOverTime.h"
#import "QNCentralManager.h"
#import "NSError+QNCentral.h"
#import <objc/runtime.h>
#import "QNCategory.h"

@implementation CBPeripheral (QNCompanyFlag)
static char CBPeripheralCompanyFlagKey;
static char CBPeripheralConnectFailFlagKey;

- (void)setQnCompanyFlag:(BOOL)qnCompanyFlag{
    setAssociatedObject(CBPeripheralCompanyFlagKey, [NSNumber numberWithBool:qnCompanyFlag])
}

- (BOOL)qnCompanyFlag {
    NSNumber *num = getAssociatedObject(CBPeripheralCompanyFlagKey)
    if (num == nil) {
        num = [NSNumber numberWithBool:NO];
    }
    return [num boolValue];
}

- (void)setQnConnectFailFlag:(BOOL)qnConnectFailFlag {
    setAssociatedObject(CBPeripheralConnectFailFlagKey, [NSNumber numberWithBool:qnConnectFailFlag])
}

- (BOOL)qnConnectFailFlag {
    NSNumber *num = getAssociatedObject(CBPeripheralConnectFailFlagKey)
    if (num == nil) {
        num = [NSNumber numberWithBool:NO];
    }
    return [num boolValue];
}

@end


#pragma mark - CBPeripheral (QNConnectOverTime)
@implementation CBPeripheral (QNConnectOverTime)
static char CBPeripheralQNTimerKey;

- (void)setTimer:(NSTimer *)timer {
    setAssociatedObject(CBPeripheralQNTimerKey, timer)
}

- (NSTimer *)timer {
    return getAssociatedObject(CBPeripheralQNTimerKey)
}

- (void)qnStartConnectTimerCentralManager:(CBCentralManager *)centralManager inTimeInterval:(NSTimeInterval)timerInterval {
    if (timerInterval == 0) return;
    [self qnCancelConnectTimer];
    __weak typeof(self) weakSelf = self;
    __weak typeof(centralManager) weakManager = centralManager;
    self.timer = [NSTimer qnCentralScheduledTimerWithTimeInterval:timerInterval block:^(NSTimer *timer) {
        [weakSelf qnCancelConnectTimer];
        [weakSelf qnRemoveObserverBlocksForKeyPath:@"state"];
        NSError *error = [NSError errorWithDomain:QNCentralDomain code:QNBleErrCodeConnectOvertime userInfo:@{NSLocalizedDescriptionKey : @"The peripheral connect overtime"}];
        if ([centralManager.delegate respondsToSelector:@selector(centralManager:didFailToConnectPeripheral:error:)]) {
            [centralManager.delegate centralManager:centralManager didFailToConnectPeripheral:self error:error];
        }
    } repeats:NO];
    
    [self qnAddObserverBlockForKeyPath:@"state" block:^(id  _Nonnull obj, id  _Nullable oldVal, id  _Nullable newVal) {
        if (weakSelf != obj) return;
        if ([newVal integerValue] != CBPeripheralStateConnecting) {
            [weakSelf qnCancelConnectTimer];
        }
        if ([newVal integerValue] != CBPeripheralStateDisconnected) return;
        [self qnRemoveObserverBlocksForKeyPath:@"state"];
        if ([oldVal integerValue] != CBPeripheralStateDisconnected && [newVal integerValue] == CBPeripheralStateDisconnected && weakManager.state != CBCentralManagerStatePoweredOn) {
            if ([oldVal integerValue] == CBPeripheralStateConnecting) {
                NSError *error = [NSError errorWithDomain:QNCentralDomain code:QNBleErrCodeStateClose userInfo:@{NSLocalizedDescriptionKey : @"The peripheral connect fail,because system blue state isn't poweredOn"}];
                if ([weakManager.delegate respondsToSelector:@selector(centralManager:didFailToConnectPeripheral:error:)]) {
                    [weakManager.delegate centralManager:weakManager didFailToConnectPeripheral:weakSelf error:error];
                }
            }else {
                NSError *error = [NSError errorWithDomain:QNCentralDomain code:QNBleErrCodeStateClose userInfo:@{NSLocalizedDescriptionKey : @"The peripheral disconnect,because system blue state isn't poweredOn"}];
                if ([weakManager.delegate respondsToSelector:@selector(centralManager:didFailToConnectPeripheral:error:)]) {
                    [weakManager.delegate centralManager:weakManager didDisconnectPeripheral:self error:error];
                }
            }
        }
    }];
}

- (void)qnCancelConnectTimer {
    [self.timer invalidate];
    self.timer = nil;
}

@end


